<!--- This is a CFQUERY-style custom tag --->
<cfsilent>
<cfif not thisTag.hasEndTag>
	<cfthrow type="Application" message="No query was given." />
</cfif>

<cfif thisTag.executionMode is 'start'>
	<!--- check and save attrbutes --->
	<cfif not StructKeyExists(attributes, "name")>
		<cfthrow type="Application" message="You must specify a query NAME attribute." />
	</cfif>
	<cfif not StructKeyExists(attributes, "datasource")>
		<cfthrow type="Application" message="You must specify a query DATASOURCE attribute with a SDB Access object." />	
	</cfif>
	<cfset maxrows = StructKeyExists(attributes, "maxrows")?attributes.maxrows:0 />
	<cfset exectime = 0 />
	<cfset sdbcalls = 0 />
<cfelse>
	<!--- parse and execute query --->
	<cfset sql = Trim(thisTag.generatedContent) />
	<cfset thisTag.generatedContent = "" />
	<cfset sqlColumns = extractColumnsFromSQL(sql) />
	<cfset qry = QueryNew("itemName", "varchar") />
	<cfset columns = [] />
	<cfloop array="#sqlColumns#" index="i">
		<cfset ArrayAppend(columns, i) />
		<cfset QueryAddColumn(qry, i, "varchar", ArrayNew()) />
	</cfloop>
	<cfset sdbqry = CreateObject("component", "sdb.Select").init(caller[attributes.datasource]) />

	<cfloop condition="true">
		<cfset timerBegin = GetPageContext().getExecutionTime() />
		<cfset result = sdbqry.execute(sql) />
		<cfset exectime += GetPageContext().getExecutionTime()-timerBegin />
		<cfset sdbcalls += 1 />
		<!--- add all found columns to query --->
		<cfloop array="#result#" index="item">
			<cfset itemData = item.toMemento().data />
			<cfset QueryAddRow(qry) />
			<cfset QuerySetCell(qry, "itemName", item.getItemName()) />
			<cfloop array="#StructKeyArray(itemData)#" index="key">
				<cfif not ArrayFindNoCase(columns, key)>
					<cfset ArrayAppend(columns, key) />
					<cfset QueryAddColumn(qry, key, "varchar", ArrayNew()) />
				</cfif>
	
				<cfset QuerySetCell(qry, key, itemData[key]) /> 
			</cfloop>
		</cfloop>	

		<cfif not (maxrows and (qry.RecordCount lt maxrows) and sdbqry.hasMore())>
			<cfbreak />
		</cfif>
	</cfloop>


	<cfset caller[attributes.name] = qry />
	<cfif StructKeyExists(attributes, "result")>
		<cfset caller[attributes.result] = {"sql":sql, "recordcount":qry.RecordCount, "cached":false, "sqlparameters":ArrayNew(), "columnList":ArrayToList(columns), "executionTime":exectime, "sdbCalls":sdbcalls, "sqlcolumns":sqlColumns} />
	</cfif>
</cfif>

<cfscript>
	private array function extractColumnsFromSQL(required string sql) {
		var result = "";
		var found = REFindNoCase("SELECT(.*?)FROM", sql, 1, true);
		if (ArrayLen(found.pos) gte 2)
			result = Trim(Mid(sql, found.pos[2], found.len[2]));
		result = ReReplace(result, "[[:space:]]","","ALL");
		result = (result neq "itemname()" and result neq "count()" and result neq "*")?result:"";
		return ListToArray(result);	
	}
</cfscript>

</cfsilent>